package dao

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/e421083458/gin_scaffold/dto"
	jwt "github.com/e421083458/gin_scaffold/public"
	"github.com/e421083458/gorm"
	"github.com/gin-gonic/gin"
	"github.com/shopspring/decimal"
	"log"
	"strings"
	"time"
)

type ListPageOutput struct {
	List  []User `form:"list" json:"list" comment:"用户列表" validate:""`
	Total int64  `form:"page" json:"page" comment:"用户总数" validate:"required"`
}

type User struct {
	Id        int       `json:"id" gorm:"column:id"`
	Name      string    `json:"name" gorm:"column:name"`
	Addr      string    `json:"addr" gorm:"column:addr"`
	Age       int       `json:"age" gorm:"column:age"`
	Birth     string    `json:"birth" gorm:"column:birth"`
	Sex       int       `json:"sex" gorm:"column:sex"`
	UpdatedAt time.Time `json:"update_at" gorm:"column:update_at"" description:"更新时间"`
	CreatedAt time.Time `json:"create_at" gorm:"column:create_at" description:"创建时间"`
}

type Address struct {
	Id       int    `json:"id"`
	Uid      int    `json:"uid "`
	Username string `json:"username"`
	Tel      string `json:"tel"`
	Province string `json:"province"`
	City     string `json:"city"`
	County   string `json:"county"`
	Detail   string `json:"detail"`
	Default  int    `json:"default"`
	Addtime  int64  `json:"addtime"`
}
type Vip struct {
	Id       int   `json:"id,omitempty"`
	Uid      int   `json:"uid,omitempty"`
	Startime int64 `json:"startime,omitempty"`
	Endtime  int64 `json:"endtime,omitempty"`
}

//提现表
type UserExtract struct {
	Id           int             `json:"id,omitempty"`
	Uid          int             `json:"uid,omitempty"`
	RealName     string          `json:"real_name"`
	ExtractType  string          `json:"extract_type,omitempty"`
	BankCode     string          `json:"bank_code,omitempty"`
	BankAddress  string          `json:"bank_address,omitempty"`
	ExtractPrice float64         `json:"extract_price,omitempty"`
	Mark         string          `json:"mark,omitempty"`
	Balance      decimal.Decimal `json:"balance,omitempty"`
	Status       int             `json:"status"`
	BankName     string          `json:"bank_name,omitempty"`
	IdNum        string          `json:"id_num, omitempty"`
	PhoneNum     string          `json:"phone_num,omitempty"`
	Addtime      time.Time       `json:"addtime,omitempty"`
}

//健康录入
type Self struct {
	Id      int    `json:"id"`
	Uid     int    `json:"uid"`
	Type    int    `json:"type"`
	Title   string `json:"title"`
	Content string `json:"content"`
	Images  string `json:"images"`
	Tag     int    `json:"tag"`
	Class   int    `json:"class"`
	Addtime int64  `json:"addtime"`
}
type Check struct {
	Id      int    `json:"id"`
	Uid     int    `json:"uid"`
	Type    int    `json:"type"`
	Title   string `json:"title"`
	Content string `json:"content"`
	Images  string `json:"images"`
	Tag     int    `json:"tag"`
	Class   int    `json:"class"`
	Addtime int64  `json:"addtime"`
}
type Analysis struct {
	Id     int    `json:"id"`
	Uid    int    `json:"uid"`
	Json   string `json:"json"`
	Kname  string `json:"kname"`
	Status string `json:"status"`
	Time   int64  `json:"time"`
	Type   int    `json:"type"`
}
type Analysis2 struct {
	Analysis
	ProductId int `json:"product_id"`
}
type Uspace struct {
	Id        int    `json:"id"`
	Truename  string `json:"truename"`
	Userphone string `json:"userphone"`
	Birthday  string `json:"birthday"`
	Spouse    int    `json:"spouse"`
	Father    int    `json:"father"`
	Mother    int    `json:"mother"`
	Sfather   int    `json:"sfather"`
	Smother   int    `json:"smother"`
	Child1    int    `json:"child1"`
	Child2    int    `json:"child2"`
	Othier    int    `json:"othier"`
}

func (f *User) TableName() string {
	return "user"
}
func (f *Uspace) SpaceBind(c *gin.Context, tx *gorm.DB, params *dto.Space) (error, *Uspace) {
	user := &Uuser{}
	err := tx.Table("hr_wx_user").Where("userphone=? and birthday=?", params.Phone, params.Birthday).First(&user).Error
	if err != nil {
		return errors.New("会员不存在"), nil
	}
	var add Uspace
	if params.Type == 1 {
		add = Uspace{Spouse: user.Id}
	} else if params.Type == 2 {
		add = Uspace{Father: user.Id}
	} else if params.Type == 3 {
		add = Uspace{Mother: user.Id}
	} else if params.Type == 4 {
		add = Uspace{Sfather: user.Id}
	} else if params.Type == 5 {
		add = Uspace{Smother: user.Id}
	} else if params.Type == 6 {
		add = Uspace{Child1: user.Id}
	} else if params.Type == 7 {
		add = Uspace{Child2: user.Id}
	} else if params.Type == 8 {
		add = Uspace{Othier: user.Id}
	}
	err = tx.Table("hr_wx_user").Where("id=?", params.Uid).Update(&add).Error
	if err != nil {
		return err, nil
	}
	return nil, &add
}
func (f *Address) Address(c *gin.Context, tx *gorm.DB) (error, []Address) {
	var res []Address

	token := c.Request.Header.Get("token") //从headers获取token
	claims, errU := jwt.ParseToken(token)
	if errU != nil {
		return errU, nil
	}
	err := tx.Table("hr_wx_address").Where("uid=?", claims.Uid).Order("id desc").Find(&res).Error
	if err != nil {
		return err, nil
	}
	return nil, res

}
func (f *Address) AddressInfo(c *gin.Context, tx *gorm.DB) (error, *Address) {
	res := &Address{}
	err := tx.Table("hr_wx_address").Order("id desc").Find(&res).Error
	if err != nil {
		return err, nil
	}
	return nil, res

}
func (f *Check) Speciallist(c *gin.Context, tx *gorm.DB, params *dto.Addlist) (error, []Check) {
	var user []Check
	err := tx.Table("hr_wx_sp").Where("uid = ? and type=?", params.Appoint, params.Type).Find(&user).Error
	if err != nil {
		return err, nil
	}
	return nil, user
}
func (f *Check) Specialinfo(c *gin.Context, tx *gorm.DB, params *dto.Addinfo) (error, *Check) {

	user := &Check{}
	err := tx.Table("hr_wx_sp").Where("id=?", params.Id).First(&user).Error
	if err != nil {
		return err, nil
	}
	return nil, user
}

//健康上传
func (f *Check) Specialhe(c *gin.Context, tx *gorm.DB, params *dto.Addday) (error, *Check) {
	add := Check{Uid: params.Uid, Type: params.Type, Title: params.Title, Content: params.Content, Images: params.Images, Tag: params.Tag, Class: params.Class, Addtime: time.Now().Unix()}
	err := tx.Table("hr_wx_sp").Create(&add).Error
	if err != nil {
		return err, nil
	}
	return nil, &add
}

func (f *Check) Checklist(c *gin.Context, tx *gorm.DB, params *dto.Addlist) (error, []Check) {
	var user []Check
	err := tx.Table("hr_wx_check").Where("uid = ? and type=?", params.Appoint, params.Type).Find(&user).Error
	if err != nil {
		return err, nil
	}
	return nil, user
}
func (f *Check) Checkinfo(c *gin.Context, tx *gorm.DB, params *dto.Addinfo) (error, *Check) {

	user := &Check{}
	err := tx.Table("hr_wx_check").Where("id=?", params.Id).First(&user).Error
	if err != nil {
		return err, nil
	}
	return nil, user
}

//健康上传
func (f *Check) Checkhe(c *gin.Context, tx *gorm.DB, params *dto.Addday) (error, *Check) {
	add := Check{Uid: params.Uid, Type: params.Type, Title: params.Title, Content: params.Content, Images: params.Images, Tag: params.Tag, Class: params.Class, Addtime: time.Now().Unix()}
	err := tx.Table("hr_wx_check").Create(&add).Error
	if err != nil {
		return err, nil
	}
	return nil, &add
}
func (f *Analysis) Anadd(c *gin.Context, tx *gorm.DB, params *dto.Ana) (error, *Analysis) {

	j := params.Json
	cc := make(map[string]json.RawMessage)
	type Json struct {
		Tag struct {
			Yuanshifen  string `json:"yuanshifen"`
			Zhuanhuafen string `json:"zhuanhuafen"`
			Jieguo      string `json:"jieguo"`
		} `json:"tag"`
	}

	e := json.Unmarshal([]byte(j), &cc)
	log.Println(cc)
	if e != nil {
		return e, nil
	}

	k := make([]string, len(cc))
	i := 0
	for s, _ := range cc {
		k[i] = s
		i++
	}
	str := strings.Replace(j, k[0], "tag", 1)
	var tag Json
	json.Unmarshal([]byte(str), &tag)

	log.Println(k[0])
	log.Println(tag.Tag.Jieguo)
	kname := k[0]
	status := tag.Tag.Jieguo
	add := Analysis{Uid: params.Uid, Json: params.Json, Kname: kname, Status: status, Time: time.Now().Unix(), Type: params.Type}
	err := tx.Table("hr_wx_cons").Create(&add).Error
	if err != nil {
		return err, nil
	}
	return nil, &add
}
func (f *Analysis) AnaList(c *gin.Context, tx *gorm.DB, uid int, typ int) (error, []Analysis) {
	var user []Analysis
	err := tx.Table("hr_wx_cons").Where("uid = ? and type =?", uid, typ).Order("id desc").Find(&user).Error
	if err != nil {
		return err, nil
	}
	return nil, user
}
func (f *Analysis2) Anainfo(c *gin.Context, tx *gorm.DB, id int) (error, *Analysis2) {
	user := &Analysis2{}
	//mes := "123"
	//log.Println(mes)
	err := tx.Table("hr_wx_cons").Where("id=?", id).First(&user).Error //hr_wx_self
	name := user.Kname
	level := user.Status
	err, ress := (&UserUnscramble{}).ChengduFind(c, tx, name, level)
	if err == nil {
		err, products := (&Product{}).FindProductByC(c, tx, ress.Id)
		if err == nil {
			log.Println(products.Id)
			user.ProductId = products.Id
		}
	}

	if err != nil {
		return err, nil
	}
	return nil, user
}
func (f *Self) Addlist(c *gin.Context, tx *gorm.DB, params *dto.Addlist) (error, []Self) {
	var user []Self
	err := tx.Table("hr_wx_self").Where("uid = ? and type=? ", params.Appoint, params.Type).Find(&user).Error
	if err != nil {
		return err, nil
	}
	return nil, user
}
func (f *Self) Addinfo(c *gin.Context, tx *gorm.DB, params *dto.Addinfo) (error, *Self) {

	user := &Self{}
	err := tx.Table("hr_wx_self").Where("id=?", params.Id).First(&user).Error
	if err != nil {
		return err, nil
	}
	return nil, user
}

//直推下级人员列表
func (f *Uuser) TuiList(c *gin.Context, tx *gorm.DB, uid int) (error, []Uuser) {

	token := c.Request.Header.Get("token") //从headers获取token
	claims, err := jwt.ParseToken(token)
	if err != nil {
		return err, nil
	}
	tuid := claims.Uid
	if uid != 0 {
		tuid = uid
	}
	log.Println(+claims.Uid)
	var user []Uuser
	err = tx.Table("hr_wx_user").Where("fromuid = ? ", tuid).Find(&user).Error
	if err != nil {
		return err, nil
	}
	return nil, user
}

//健康上传
func (f *Self) Addhe(c *gin.Context, tx *gorm.DB, params *dto.Addday) (error, *Self) {
	add := Self{Uid: params.Uid, Type: params.Type, Title: params.Title, Content: params.Content, Images: params.Images, Tag: params.Tag, Class: params.Class, Addtime: time.Now().Unix()}
	err := tx.Table("hr_wx_self").Create(&add).Error
	if err != nil {
		return err, nil
	}
	return nil, &add
}

//完善个人资料
func (f *Uuser) Perset(c *gin.Context, tx *gorm.DB, params *dto.UserInfo) (error, *Uuser) {

	add := Uuser{Truename: params.TrueName, Headimgurl: params.Headimgurl, Userphone: params.UserPhone, Sex: params.Sex, Birthday: params.Birthday,
		IdCard: params.IdCard}

	err := tx.Table("hr_wx_user").Where("id=?", params.Uid).Update(&add).Error
	if err != nil {
		return err, nil
	}
	user := Uuser{}
	err2 := tx.Table("hr_wx_user").Where("id = ?", params.Uid).First(&user).Error

	if err2 != nil {
		return err2, nil
	}
	return nil, &user

}

//核销码列表
func (f *Wcode2) CodeList(c *gin.Context, tx *gorm.DB, uid int, status int) (error, []Wcode2) {
	log.Println(uid)

	var wcodes []Wcode2
	if status > 0 {
		if status == 1 {
			state := 0
			err := tx.Table("hr_wx_wcode").Where("fid=? and status=?", uid, state).Find(&wcodes).Error
			if err != nil {
				return err, nil
			}
		} else {
			state := 1
			err := tx.Table("hr_wx_wcode").Where("fid=? and status=?", uid, state).Find(&wcodes).Error
			if err != nil {
				return err, nil
			}
		}
	} else {
		err := tx.Table("hr_wx_wcode").Where("fid=?", uid).Find(&wcodes).Error
		if err != nil {
			return err, nil
		}
	}

	return nil, wcodes
}

//核销核销码
func (f *Wcode) CheckCode(c *gin.Context, tx *gorm.DB, params *dto.CkCode) (error, *Wcode) {

	var codeInfo Wcode
	tx.Table("hr_wx_wcode").Where("fid=? and tcode=?", params.Fid, params.Tcode).First(&codeInfo)
	//log.Println(codeInfo)
	//log.Println(codeInfo.Tcode)
	//log.Println(len(codeInfo.Tcode))
	//判断是否有效 不存在
	if len(codeInfo.Tcode) == 0 {
		codeInfo.Msg = "激活码不存在"
		return errors.New("激活码不存在"), &codeInfo
	} else {
		//这是存在
		if codeInfo.Status == 1 {
			//log.Println("1-----")
			//log.Println(codeInfo.Uid)
			codeInfo.Msg = "已经激活过,不可重复激活"
			return errors.New(""), &codeInfo
		} else {
			ups := Wcode{Status: 1, Uid: params.Uid, ActiveTime: time.Now().Unix()}
			//log.Println("2-----")
			//log.Println(codeInfo.Id)
			//更新激活状态
			err := tx.Table("hr_wx_wcode").Where("id=?", codeInfo.Id).Update(&ups).Error
			if err != nil {
				return err, nil
			} else {
				//log.Println("3-----")
				//log.Println(params.Uid)
				err, user := (&Uuser{}).FindUser(c, tx, params.Uid)
				if err != nil {
					return err, nil
				} else {
					//判断更新上一级，如果没有上一级，则更新上
					if user.Fromuid == 0 {
						fromuid := params.Fid
						err = tx.Debug().Table("hr_wx_user").Where("id = ?", params.Uid).Update("fromuid", fromuid).Error
						if err != nil {
							return err, nil
						}
					}
					//充值一年的会员
					if codeInfo.Ctype == 1 {
						now := user.Endtime + 12*86400*30

						err = tx.Debug().Table("hr_wx_user").Where("id = ?", params.Uid).Update("Endtime", now).Error
						if err != nil {
							return err, nil
						}
					}
					//充值两年的会员
					if codeInfo.Ctype == 2 {
						now := user.Endtime + 24*86400*30
						err = tx.Table("hr_wx_user").Where("id = ?", params.Uid).Update("Endtime", now).Error
						if err != nil {
							return err, nil
						}
					}
					codeInfo.Msg = "会员激活成功"
				}
			}
		}

	}
	return nil, &codeInfo

}
func (f *Address) AddressAdd(c *gin.Context, tx *gorm.DB, params *dto.Address) (error, int) {
	token := c.Request.Header.Get("token") //从headers获取token
	claims, err := jwt.ParseToken(token)
	//uid := claims.Uid
	add := Address{Uid: claims.Uid, Username: params.Username, Tel: params.Tel, Province: params.Province, City: params.City, County: params.County, Detail: params.Detail, Default: params.Default, Addtime: time.Now().Unix()}
	fmt.Println(add)
	errs := tx.Table("hr_wx_address").Create(&add).Error
	if errs != nil {
		return err, 0
	}
	return nil, add.Id

}
func (f *UserExtract) UserExtractAdd(c *gin.Context, tx *gorm.DB, params *dto.UserExtract) (error, int) {
	token := c.Request.Header.Get("token") //从headers获取token
	claims, err := jwt.ParseToken(token)
	//uid := claims.Uid
	user := &Uuser{}
	erru := tx.Table("hr_wx_user").Where("id=?", claims.Uid).First(&user).Error
	if erru != nil {
		return erru, claims.Uid
	}

	adds := UserExtract{Uid: claims.Uid, RealName: user.Truename, ExtractType: "bank", BankCode: user.IdCard, BankAddress: params.BankAddress, ExtractPrice: params.ExtractPrice,
		Mark: params.Mark, Balance: user.Money, Status: 0, BankName: params.BankName, IdNum: params.IdNum, PhoneNum: user.Userphone, Addtime: time.Now()}
	fmt.Println(adds)
	errs := tx.Table("hr_user_extract").Create(&adds).Error
	if errs != nil {
		return err, 0
	} else {
		fmt.Println(adds)
	}
	return nil, adds.Id
}
func (f *UserExtract) UserExtract(c *gin.Context, tx *gorm.DB) (error, []UserExtract) {
	token := c.Request.Header.Get("token") //从headers获取token
	claims, err0 := jwt.ParseToken(token)
	if err0 != nil {
		return err0, nil
	}
	var res []UserExtract
	err := tx.Table("hr_user_extract").Where("uid=?", claims.Uid).Order("id desc").Find(&res).Error //and status=1
	if err != nil {
		return err, nil
	}
	return nil, res

}
func (f *Address) AddressUp(c *gin.Context, tx *gorm.DB, params *dto.Address) (error, int) {
	token := c.Request.Header.Get("token") //从headers获取token
	claims, errU := jwt.ParseToken(token)
	if errU != nil {
		return errU, 0
	}
	uid := claims.Uid
	up := Address{Uid: uid, Username: params.Username, Tel: params.Tel, Province: params.Province, City: params.City, County: params.County, Detail: params.Detail, Default: params.Default, Addtime: time.Now().Unix()}
	fmt.Println(up)
	err := tx.Table("hr_wx_address").Where("id = ?", params.Id).Update(&up).Error
	if err != nil {
		return err, 0
	}
	return nil, up.Id

}
func (f *User) Del(c *gin.Context, tx *gorm.DB, idSlice []string) error {
	err := tx.SetCtx(jwt.GetGinTraceContext(c)).Where("id in (?)", idSlice).Delete(&User{}).Error
	if err != nil {
		return err
	}
	return nil
}
func (f *Vip) Vip(c *gin.Context, tx *gorm.DB, uid int) (error, []Vip) {
	var user []Vip
	err := tx.Table("hr_wx_vip").Where("uid = ?", uid).First(&user).Error
	if err != nil {
		return err, nil
	}

	return nil, user
}

//会员有效期或次数判断
func (f *Pulse) CheckPt(c *gin.Context, tx *gorm.DB, id, uid, t int) (bool, error) {
	err, user := (&Uuser{}).FindUser(c, tx, uid)
	if err != nil {
		return false, err
	}
	if time.Now().Unix() > user.Endtime {
		return false, errors.New("会员已过期")
	}
	if user.Times <= 0 {
		return false, errors.New("可用次数不足")
	}
	return true, nil
}

//会员有效期或次数判断
func (f *Vip) CheckVip(c *gin.Context, tx *gorm.DB, uid int) (bool, error) {

	err, vip := (&Vip{}).Vip(c, tx, uid)
	if err != nil {
		return false, err
	}
	if len(vip) < 1 {
		return false, errors.New("未开通超级会员")
	}
	if time.Now().Unix() > vip[0].Endtime {
		return false, errors.New("超级会员已过期")
	}
	return true, nil
}
func (f *Pulse) Lock(c *gin.Context, tx *gorm.DB, id, uid, t int) (bool, error) {
	//五脏
	err, user := (&Uuser{}).FindUser(c, tx, uid)
	if err != nil {
		return false, err
	}

	if user.Times <= 0 {
		return false, errors.New("可用次数不足")
	}
	//todo 会员已经过期*********************************
	//超级会员是否过期

	if time.Now().Unix() > user.Endtime {
		//超级会员未过期可继续使用
		_, err := (&Vip{}).CheckVip(c, tx, uid)
		if err != nil {
			return false, errors.New("会员已过期")
		}

	}
	if user.Times == 1 {
		err = tx.Table("hr_wx_user").Where("id = ?", uid).Update("Times", 0).Error
	} else {
		update := &Uuser{Times: user.Times - 1}
		err = tx.Table("hr_wx_user").Where("id = ?", uid).Update(&update).Error
	}

	if err != nil {
		return false, err
	}
	if t == 1 {
		wzuppdate := &UserWuzhang{Lock: 1}
		err = tx.Table("hr_wx_wuzhang").Where("pid = ?", id).Update(&wzuppdate).Error
		if err != nil {
			return false, err
		}
	} else if t == 2 {
		liufuuppdate := &UserLiufu{Lock: 1}
		err = tx.Table("hr_wx_liufu").Where("pid = ?", id).Update(&liufuuppdate).Error
		if err != nil {
			return false, err
		}
	} else if t == 3 {
		tizhiuppdate := &Tizhi{Lock: 1}
		err = tx.Table("hr_wx_tizhi").Where("pid = ?", id).Update(&tizhiuppdate).Error
		if err != nil {
			return false, err
		}
	} else if t == 4 {
		dbuppdate := &Dabing{Lock: 1}
		err = tx.Table("hr_wx_dabing").Where("pid = ?", id).Update(&dbuppdate).Error
		if err != nil {
			return false, err
		}
	} else {
		return false, errors.New("类型不可用")
	}
	return true, nil
}
func (f *User) Find(c *gin.Context, tx *gorm.DB, id int64) (*User, error) {
	var user *User
	err := tx.SetCtx(jwt.GetGinTraceContext(c)).Where("id = ?", id).First(user).Error
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (f *User) PageList(c *gin.Context, tx *gorm.DB, params *dto.ListPageInput) ([]User, int64, error) {
	var list []User
	var count int64
	offset := (params.Page - 1) * params.PageSize
	query := tx.SetCtx(jwt.GetGinTraceContext(c))
	if params.Name != "" {
		query = query.Where("name = ?", params.Name)
	}
	err := query.Limit(params.PageSize).Offset(offset).Find(&list).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, 0, err
	}
	errCount := query.Table("user").Count(&count).Error
	if errCount != nil {
		return nil, 0, err
	}
	return list, count, nil
}

func (f *User) Save(c *gin.Context, tx *gorm.DB) error {
	if err := tx.SetCtx(jwt.GetGinTraceContext(c)).Save(f).Error; err != nil {
		return err
	}
	return nil
}
